package cn.blnp.net.flowable.event.start.timer;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * <h3>开始事件-定时器开始事件</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/5/7 10:19
 */
@Slf4j
@SpringBootTest
public class TimerEventTest {

    @Resource
    private RuntimeService runtimeService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private TaskService taskService;

    /**
     *  <p>
     *      定时器开始事件用于在指定的时间启动一个流程，或者在指定周期内循环启动多次流程，如在2025年1月1日10时整发起年度目标审核流程，或每月1日0时启动账务结算处理流程。
     *  当满足设定的时间条件时，定时器开始事件被触发，从而启动流程。
     *  </p>
     *  <pre>
     *      {@code
     *          <!-- 定义开始节点 -->
     *          <startEvent id="timerStart" >
     *              <timerEventDefinition>
     *                  <!-- 流程会根据指定的时间启动一次 -->
     *                  <timeDate>2024-03-14T12:13:14</timeDate>
     *              </timerEventDefinition>
     *          </startEvent>
     *      }
     *  </pre>
     *  <h3>演示案例：</h3>
     *  <p>流程定义文件：{@link flow/timerEventTest.bpmn20.xml}</p>
     *  <p>流程预览图：<img src="https://free4.yunpng.top/2025/05/07/681ad0dd9a321.png" /></p>
     **/
    @Test
    public void test() {
        /**
         *  在以上流程定义中，加粗部分的代码定义了一个定时器开始事件，为定时器配置了timeDuration子元素，PT1M表示定时器开始事件将在1分钟后触发。特别注意以下几个问题：
         *  1、子流程中不能嵌入定时器开始事件。
         *  2、定时器开始事件是从流程部署开始计时的，到了指定的时间点会自动触发，无须调用运行时服务的“startProcessInstanceBy…”系列方法发起流程实例。如果调用，则会在定时启动之外额外启动一个流程。
         *  3、当嵌入定时器开始事件的流程部署新版本时，上一版本流程中的定时器作业会被移除（从而被当成一个普通的空开始事件处理），这是因为通常并不需要旧版本的流程仍然自动发起新的流程实例。
         **/
        Deployment deploy = repositoryService.createDeployment()
                .name("定时器开始事件演示")
                .addClasspathResource("flow/timerEventTest.bpmn20.xml")
                .deploy();
        log.info("部署成功，流程ID：{}", deploy.getId());
        // 启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerEventTest");
        log.info("流程实例ID：{}", processInstance.getId());
        //因为设计的流程是在一分钟后启动流程，所以需要等待1分钟
        try {
            Thread.sleep(90*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //查询此时流程实例的任务信息
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .singleResult();
        log.info("任务ID：{}", task.getId());
        log.info("任务名称：{}", task.getName());
        log.info("任务审批人：{}", task.getAssignee());
        log.info("任务创建时间：{}", task.getCreateTime());

        /**
         *  演示结果：
         * 2025-05-07 11:58:24.308  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 部署成功，流程ID：85c5643c-2af7-11f0-a343-50ebf6ec8f6d
         * 2025-05-07 11:58:24.361  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 流程实例ID：8612e802-2af7-11f0-a343-50ebf6ec8f6d
         * 2025-05-07 11:59:54.388  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 任务ID：86142087-2af7-11f0-a343-50ebf6ec8f6d
         * 2025-05-07 11:59:54.388  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 任务名称：数据采集
         * 2025-05-07 11:59:54.388  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 任务审批人：null
         * 2025-05-07 11:59:54.388  INFO 20780 --- [           main] c.b.n.f.e.start.timer.TimerEventTest     : 任务创建时间：Wed May 07 11:58:24 CST 2025
         **/
    }
}
